package com.zgj.netty_udp.server;

import com.zgj.netty_udp.utils.CRC16;
import com.zgj.netty_udp.utils.SpringUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import lombok.extern.log4j.Log4j2;

@Log4j2
public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    MessageProcessor messageProcessor = SpringUtil.getBean(MessageProcessor.class);

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
        System.out.println("原始数据=============");
        ByteBuf byteBuf = msg.content();
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        if (bytes.length > 2) {
            String crc = CRC16.bytesToHexString(new byte[]{bytes[bytes.length - 1], bytes[bytes.length - 2]});
            String getCrc = Integer.toHexString(CRC16.getCRC1021(bytes, bytes.length - 2)).toUpperCase();
            log.info("CRC16====={}", crc);
            log.info("Rcrc======{}", getCrc);
            if (crc.equals(getCrc)) {
                log.info("数据正常，解析存储");

                messageProcessor.produce(ctx.channel(), bytes);
                byte[] reqBytes = bytes.clone();
                if (reqBytes[5] == 1) {
                    ctx.writeAndFlush(new DatagramPacket(Unpooled.wrappedBuffer(CRC16.createPkg(reqBytes, 50)), msg.sender()));
                }
            } else {
                log.warn("数据异常，返回重发");
                ctx.writeAndFlush(new DatagramPacket(Unpooled.wrappedBuffer(CRC16.createPkg(bytes, 51)), msg.sender()));
            }
        }
    }


    /**
     * 处理异常, 一般将实现异常处理逻辑的Handler放在ChannelPipeline的最后
     * 这样确保所有入站消息都总是被处理，无论它们发生在什么位置，下面只是简单的关闭Channel并打印异常信息
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
